

#include <iostream>
#include <string>
#include <ctemplate/template.h>
#include <jsoncpp/json/json.h>
#include <filesystem>
#include "cryptopp/cryptlib.h"
#include "cryptopp/base64.h"
#include "cryptopp/filters.h"
#include <cryptopp/rsa.h>
#include <cryptopp/osrng.h>
#include <cryptopp/hex.h>
#include <cryptopp/modes.h>
#include <cryptopp/aes.h>

#include "./SQL/Sql.hpp"
#include "./mail/mailt.h"

void ExpandHtml(std::string *html)
{
    // 1. 形成路径
    std::string src_html = "./NAV/index.html";
    ctemplate::TemplateDictionary root("index");

    // 3. 获取被渲染的html
    ctemplate::Template *tpl = ctemplate::Template::GetTemplate(src_html, ctemplate::DO_NOT_STRIP);
    tpl->Expand(html, &root);
}
bool verifyUserByEmailPasswordAndMachineCode(MYSQL *my, const std::string &email, const std::string &password_or_captcha, const std::string &machineCode, const LoginType &logintype, std::string *out)
{
    if (logintype == LoginType::WITH_PWd)
    {
        return Login_withPwd(my, email, password_or_captcha, machineCode, out);
    }
    else
    {
        return Login_withCaptcha(my, email, password_or_captcha, machineCode, out);
    }

    return true;
}
bool validateUser(const std::string &email, const std::string &password, const std::string &machinecode, const LoginType &logintype, std::string *out)
{
    bool res = false;
    MYSQL *my = init_MYSQL();
    res = verifyUserByEmailPasswordAndMachineCode(my, email, password, machinecode, logintype, out);
    return res;
}
void handle_get_images(const httplib::Request &req, httplib::Response &res)
{
    std::vector<Json::Value> image_files_info;
    // 遍历指定目录下的文件
    std::cout << "get" << std::endl;
    for (const auto &entry : std::filesystem::directory_iterator("./NAV/images"))
    {
        if (entry.is_regular_file())
        {
            std::string file_extension = entry.path().extension().string();
            // 判断是否为常见的图片文件扩展名
            if (file_extension == ".jpg" || file_extension == ".png" || file_extension == ".jpeg" || file_extension == ".gif")
            {
                std::string file_name = entry.path().filename().string();
                std::string file_path = entry.path().string();
                // 读取文件内容
                std::ifstream file(file_path, std::ios::binary);
                if (file.is_open())
                {
                    file.seekg(0, std::ios::end);
                    std::streamsize file_size = file.tellg();
                    file.seekg(0, std::ios::beg);
                    std::vector<char> buffer(file_size);
                    file.read(buffer.data(), file_size);

                    // 使用Crypto++进行Base64编码
                    std::string encoded_content;
                    CryptoPP::byte *byte_buffer = reinterpret_cast<CryptoPP::byte *>(buffer.data());

                    // 使用转换后的字节数组传递给 StringSource
                    CryptoPP::StringSource(byte_buffer, buffer.size(), true,
                                           new CryptoPP::Base64Encoder(
                                               new CryptoPP::StringSink(encoded_content), false));
                    // std::cout << encoded_content << std::endl;
                    //  将文件名和文件内容（二进制形式）封装为JSON对象
                    Json::Value file_info;
                    file_info["filename"] = file_name;
                    file_info["content"] = encoded_content; //./std::string(buffer.begin(), buffer.end());
                    image_files_info.push_back(file_info);

                    file.close();
                }
            }
        }
    }

    if (!image_files_info.empty())
    {
        // 将所有图片文件信息转换为JSON数组
        Json::Value response_json(Json::arrayValue);
        for (const auto &info : image_files_info)
        {
            response_json.append(info);
        }
        Json::Value response;
        response["image_files_info"] = response_json;

        // 设置响应内容为JSON字符串，设置正确的Content-Type
        res.set_content(response.toStyledString(), "application/json");
        res.status = 200;
    }
    else
    {
        res.status = 404;
        res.set_content("No image files found in the specified directory", "text/plain");
    }
}
inline static std::string generate_verification_code()
{
    std::srand(std::time(0));
    std::ostringstream oss;
    for (int i = 0; i < 6; ++i)
    {
        oss << std::rand() % 10;
    }
    return oss.str();
}
int main()
{

    std::string html;
    ExpandHtml(&html);

    // 用户请求的服务路由功能
    Server svr;

    svr.Get("/download/(.*)", [](const httplib::Request &req, httplib::Response &res)
            {
        std::string file_name = req.matches[1];
        std::string full_file_path = "./NAV/downloads/" + file_name; 

        std::ifstream file(full_file_path, std::ios::binary);
        if (file.is_open()) {
            // 获取文件大小
            file.seekg(0, std::ios::end);
            std::streamsize file_size = file.tellg();
            file.seekg(0, std::ios::beg);

            // 分配缓冲区并读取文件内容到缓冲区
            char* buffer = new char[file_size];
            file.read(buffer, file_size);

            // 设置响应内容为文件内容
            res.set_content(buffer, file_size, "application/octet-stream");

            // 设置响应头中的Content-Disposition字段，用于告知客户端文件名
            res.set_header("Content-Disposition", "attachment; filename=\"" + file_name + "\"");

            delete[] buffer;
            file.close();
        }
        else {
            res.status = 404;
            res.set_content("File not found", "text/plain");
        } });
    svr.Get("/NAV", [&](const Request &req, Response &res)
            {
        std::cout << "get" << std::endl;
        res.set_content(html, "text/html; charset=utf-8"); });

    // 密码登录
    svr.Post("/api/login_with_password", [](const httplib::Request &req, httplib::Response &res)
             {
        // 解析 JSON 请求体
        Json::Value json_data;
        Json::CharReaderBuilder reader;
        std::string errs;
        std::istringstream s(req.body);
        bool parsingSuccessful = Json::parseFromStream(reader, s, &json_data, &errs);
        if (!parsingSuccessful) {
            res.status = 400;
            res.set_content("Invalid JSON", "text/plain");
            return;
        }
 
        // 获取用户名和密码
        std::string email = json_data["email"].asString();
        std::string password = json_data["password"].asString();
        std::string machinecode = json_data["machinecode"].asString();
        //CryptoPP::StringSource(password.c_str(), true);
        // 验证用户
        // 生成随机密钥和 IV
    // CryptoPP::AutoSeededRandomPool rnd;
    // CryptoPP::byte key[CryptoPP::AES::DEFAULT_KEYLENGTH];
    // CryptoPP::byte iv[CryptoPP::AES::BLOCKSIZE];
    // rnd.GenerateBlock(key, sizeof(key));
    // rnd.GenerateBlock(iv, sizeof(iv));

    // // 使用 CBC 模式的 AES 加密
    // std::string ciphertext;
    
    //     CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encryptor;
    //     encryptor.SetKeyWithIV(key, sizeof(key), iv);

    //     CryptoPP::StringSource ss(password, true,
    //         new CryptoPP::StreamTransformationFilter(encryptor,
    //             new CryptoPP::StringSink(ciphertext)
    //         )
    //     );
    

    // // 输出加密后的密文（以十六进制表示）
    // std::string encoded_password;
    // CryptoPP::StringSource(ciphertext, true,
    //     new CryptoPP::HexEncoder(
    //         new CryptoPP::StringSink(encoded_password)
    //     )
    // );

        std::string response_str;
        if (validateUser(email, password, machinecode, LoginType::WITH_PWd, &response_str)) {
            // 构建响应
            
            Json::Value response;
            response["success"] = true;
            response["message"] = "Login successful";
            //response["response_str"] = response_str;
            response["userName"] = GetUserName(email, &response_str);
            // 设置响应内容和类型
            Json::StreamWriterBuilder writer;   
            std::string response_str = Json::writeString(writer, response);
            res.set_content(response_str, "application/json");
            res.status = 200;
        } else {
            // 构建错误响应
            Json::Value response;
            response["success"] = false;
            response["message"] = "Invalid username or password";
            response["response_str"] = response_str;

            // 设置响应内容和类型
            Json::StreamWriterBuilder writer;
            std::string response_str = Json::writeString(writer, response);
            res.set_content(response_str, "application/json");
            res.status = 401; 
        } });

    // 验证码登录
    svr.Post("/api/login_with_captcha", [](const httplib::Request &req, httplib::Response &res)
             {
        // 解析 JSON 请求体
        Json::Value json_data;
        Json::CharReaderBuilder reader;
        std::string errs;
        std::istringstream s(req.body);
        bool parsingSuccessful = Json::parseFromStream(reader, s, &json_data, &errs);
        if (!parsingSuccessful) {
            res.status = 400;
            res.set_content("Invalid JSON", "text/plain");
            return;
        }
 
        // 获取用户名和验证码
        std::string email = json_data["email"].asString();
        std::string captcha= json_data["captcha"].asString();
        std::string machinecode = json_data["machinecode"].asString();
        // 验证用户
        std::string response_str;
        if (validateUser(email, captcha, machinecode, LoginType::WITH_CAPTCHA, &response_str)) {
            // 构建响应

            
            Json::Value response;
            response["success"] = true;
            response["message"] = "Login successful";
            //response["response_str"] = response_str;
            response["userName"] = GetUserName(email, &response_str);
            // 设置响应内容和类型
            Json::StreamWriterBuilder writer;
            std::string response_str = Json::writeString(writer, response);
            res.set_content(response_str, "application/json");
            res.status = 200;
        } else {
            // 构建错误响应
            Json::Value response;
            response["success"] = false;
            response["message"] = "Invalid username or captcha";
            response["response_str"] = response_str;

            // 设置响应内容和类型
            Json::StreamWriterBuilder writer;
            std::string response_str = Json::writeString(writer, response);
            res.set_content(response_str, "application/json");
            res.status = 401; 
        } });

    // 注册
    svr.Post("/api/register", [&](const Request &req, Response &res)
             {
                 Json::Value json_data;
                 Json::CharReaderBuilder reader;
                 std::string errs;
                 std::istringstream s(req.body);
                 bool parsingSuccessful = Json::parseFromStream(reader, s, &json_data, &errs);
                 if (!parsingSuccessful)
                 {
                     res.status = 400;
                     res.set_content("Invalid JSON", "text/plain");
                     return;
                 }
                 // 获取用户名和密码
                 std::string username = json_data["username"].asString();
                 std::string password = json_data["password"].asString();
                 std::string email = json_data["email"].asString();
                 std::string machinecode = json_data["machinecode"].asString();
                 std::string Captcha = json_data["captcha"].asString();
                 // 验证用户
                 
    // CryptoPP::AutoSeededRandomPool rnd;
    // CryptoPP::byte key[CryptoPP::AES::DEFAULT_KEYLENGTH];
    // CryptoPP::byte iv[CryptoPP::AES::BLOCKSIZE];
    // rnd.GenerateBlock(key, sizeof(key));
    // rnd.GenerateBlock(iv, sizeof(iv));

    // // 使用 CBC 模式的 AES 加密
    // std::string ciphertext;
    
    //     CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encryptor;
    //     encryptor.SetKeyWithIV(key, sizeof(key), iv);

    //     CryptoPP::StringSource ss(password, true,
    //         new CryptoPP::StreamTransformationFilter(encryptor,
    //             new CryptoPP::StringSink(ciphertext)
    //         )
    //     );
    

    // 输出加密后的密文（以十六进制表示）
    // std::string encoded_password;
    // CryptoPP::StringSource(ciphertext, true,
    //     new CryptoPP::HexEncoder(
    //         new CryptoPP::StringSink(encoded_password)
    //     )
    // );

                 std::string response_str;
                 if (Register(username, email, password, machinecode, Captcha, &response_str))
                 {
                    Json::Value response;
                    response["success"] = true;
                    response["message"] = "register successful";
                    response["userName"] = GetUserName(email, &response_str);
                    // 设置响应内容和类型
                    Json::StreamWriterBuilder writer;
                    std::string response_str = Json::writeString(writer, response);
                    res.set_content(response_str, "application/json");
                    res.status = 200;
                 }
                 else
                 {
                     // 构建错误响应
                     Json::Value response;
                     response["success"] = false;
                     response["message"] = "insert error";
                    response["response_str"] = response_str;
                     // 设置响应内容和类型
                     Json::StreamWriterBuilder writer;
                     std::string response_str = Json::writeString(writer, response);
                     res.set_content(response_str, "application/json");
                     res.status = 401;
                 } });

    // 设置静态文件目录
    svr.set_mount_point("/images", "./NAV/images");

    // 发送邮箱验证码
    svr.Post("/mail/captcha", [&](const httplib::Request &req, httplib::Response &res)
             {
                 Json::Value json_data;
                 Json::CharReaderBuilder reader;
                 std::string errs;
                 std::istringstream s(req.body);
                 bool parsingSuccessful = Json::parseFromStream(reader, s, &json_data, &errs);
                 if (!parsingSuccessful)
                 {
                     res.status = 400;
                     res.set_content("Invalid JSON", "text/plain");
                     return;
                 }
                 // 获取用户名和密码
                 std::string email = json_data["email"].asString();
                 std::string machinecode = json_data["machinecode"].asString();

                 std::cout << email << std::endl;
                 // 生成验证码
                 std::string Generate_Code = generate_verification_code();
                 char recogize_code[Generate_Code.length() + 1];
                 std::strcpy(recogize_code, Generate_Code.c_str());

                 std::string strMessage = recogize_code;

                 std::vector<std::string> vecTo; // 发送列表
                 vecTo.push_back(email);

                 std::vector<std::string> ccList;
                 std::vector<std::string> attachment;
                 SmtpBase *base;
                 SimpleSmtpEmail m_mail("smtp.163.com", "25");
                 base = &m_mail;
                 // base->SendEmail(from, passs, to, subject, strMessage);//普通的文本发送，明文发送

                 SimpleSslSmtpEmail m_ssl_mail("smtp.163.com", "465");
                 base = &m_ssl_mail;
                 // base->SendEmail(from, passs, to, subject, strMessage);
                 base->SendEmail(ServerEmail, ServerEmail_Pwd, vecTo, Email_Subject, strMessage, attachment, ccList);

                std::string out;
                Update_after_sendCaptcha(email, recogize_code, machinecode, &out); });

    svr.Get("/refresh", handle_get_images);
    svr.set_base_dir("./NAV");
    svr.listen("0.0.0.0", 8080);
    return 0;
}